/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2018, hathach (tinyusb.org)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * This file is part of the TinyUSB stack.
 */



/*
有关tinyUSB 设备开发的流程
需要实现以下函数
	void dcd_init (uint8_t rhport);								初始化设备
	void dcd_disconnect(uint8_t rhport);						断开连接
	void dcd_connect(uint8_t rhport);							开启连接
	void dcd_sof_enable(uint8_t rhport, bool en);				SOF开启.可不实现
	void dcd_int_enable (uint8_t rhport);						开启中断
	void dcd_int_disable(uint8_t rhport);						禁用中断
	void dcd_set_address(uint8_t rhport, uint8_t dev_addr);		设置设备地址.
		需要注意有些设备不能直接在该函数更改设备地址.  需要在dcd_edpt0_status_complete() 里实现
			应该是USB回复主机时.需要初始化的地址.
	void dcd_remote_wakeup(uint8_t rhport);						远程唤醒
	void dcd_int_handler(uint8_t rhport);						处理中断程序
	void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request);
		可不实现,但有些设备针对dcd_set_address的问题必须实现.如stm32
		不过有些设备可能需要处理端口0的状态. 具体查阅有关USB端口0的一些协议内容
	bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc);
		打开端口,分配最大缓存
	void dcd_edpt_close_all (uint8_t rhport);					可不实现
	void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr);		可不实现
	bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes);
		tinyUSB处理读写包的函数.数据量可能会超过maxpacket. 会切割发送.
		当发送完成后.调用dcd_event_xfer_complete函数
	bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes);
		可不实现
	void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr);		USB设置stall
	void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr);USB清除stall


USB初始化流程
	1.配置中断与设备地址
	2.当触发中断时,状态是RESET. 则初始化端口0的输入与输出. 类型是CONTROL
	3.USB触发RX事件,一般为USB SETUP事件.会分配devaddr.
		但tinyUSB会把给事件放到事件队列里(并且设置为NAK状态).有主程序执行该事件.
		主程序执行该事件,调用dcd_set_address(实际上是发送VALID状态).
		接着触发TX中断事件(dcd_set_address实际上是发送TX 0个数据.表示发送完成). 把该事件放到tinyUSB队列.让主程序处理该事件
			主程序处理该事件会调用dcd_edpt0_status_complete
		然后调用dcd_edpt0_status_complete来初始化设备的devaddr.
	4.完成上面的设置后.会自己调用类似example实现的USB枚举

	5.TINYUSB很多时候类似阻塞型传输数据.
		比如接收到控制命令或者.则传输至tinyusb的上下文.直接回复ACK.
		然后主线程(task)处理tinyusb上下文事件.负责传输回复数据(fifo到tinyusb的缓存包)
			如果要即时发送.则需要xxx_write_flush
				(一般xxx_write 相当于fifo输出数据.只要大于包的大小(一般为64)才开始flush)
				所谓的flush.其实就是直接usbd_edpt_xfer (往USB RAM塞数据)
		在接收数据时.主线程(task)处理接收数据
			xxx_read获得数据(顺序如下.<stm32>)
				实际上是在dcd_edpt_xfer 函数内设置缓存.并且设置RX状态为接收
				实际上还在等待rx接收
			当rx接收数据指定长度完成时.触发dcd_event_xfer_complete (为主线程(task)添加事件)
			主线程调用 driver->xfer_cb 处理<接收完成>回调函数



*/

#include "tusb_option.h"
#include "common/tusb_compiler.h"
#include "device/dcd.h"
#if CFG_TUSB_MCU == 8800 || 1
#include "at32f403a_407_conf.h"
#include "at32f403a_407_usb.h"
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+

static usb_ept_info ept_out[8];
static usb_ept_info ept_in[8];
static uint8_t setup_buffer[12];              /*!< usb setup request buffer */

static const tusb_desc_endpoint_t ep0OUT_desc =
{
  .bLength          = sizeof(tusb_desc_endpoint_t),
  .bDescriptorType  = TUSB_DESC_ENDPOINT,

  .bEndpointAddress = 0x00,
  .bmAttributes     = { .xfer = TUSB_XFER_CONTROL },
  .wMaxPacketSize   = CFG_TUD_ENDPOINT0_SIZE,
  .bInterval        = 0
};

static const tusb_desc_endpoint_t ep0IN_desc =
{
  .bLength          = sizeof(tusb_desc_endpoint_t),
  .bDescriptorType  = TUSB_DESC_ENDPOINT,

  .bEndpointAddress = 0x80,
  .bmAttributes     = { .xfer = TUSB_XFER_CONTROL },
  .wMaxPacketSize   = CFG_TUD_ENDPOINT0_SIZE,
  .bInterval        = 0
};

/////////////////////////////////////
//该定义为at32f403a
#define	INT_EN(en) \
	if(en){ nvic_irq_enable(USBFS_L_CAN1_RX0_IRQn,0,0); nvic_irq_enable(USBFSWakeUp_IRQn,0,0);  } \
	else{   nvic_irq_disable(USBFS_L_CAN1_RX0_IRQn); nvic_irq_disable(USBFSWakeUp_IRQn); }

#define CONNECT \
	USB->ctrl_bit.disusb = 0;USB->cfg_bit.puo = 0;

#define DISCONNECT \
	USB->ctrl_bit.disusb = 1;USB->cfg_bit.puo = 1;

#define WAKEUP \
	USB->ctrl_bit.gresume = 1;

#define SET_ADDR(addr) \
	USB->devaddr_bit.addr = addr; USB->devaddr_bit.cen = 1;

#define MAX_EP_COUNT 8u
#define STFSDEV_EP_COUNT (8u)


static void dcd_transmit_packet(int ept_num);
//////////////////////////////////////////////////////////////////////////////////////////////////
//定义结构体
static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6];

static uint8_t* ept_recv_buf[MAX_EP_COUNT];
static uint16_t ept_recv_len[MAX_EP_COUNT];
static uint16_t ept_recv_off[MAX_EP_COUNT];

static uint8_t* ept_send_buf[MAX_EP_COUNT];
static uint16_t ept_send_len[MAX_EP_COUNT];
static uint16_t ept_send_off[MAX_EP_COUNT];

static uint16_t ept_buf_addr[MAX_EP_COUNT][2];
static uint16_t ept_max_packet_size[MAX_EP_COUNT][2];

typedef struct{
	uint32_t tx_addr;
	uint32_t tx_len;	// [9:0],其他保留
	uint32_t rx_addr;
	uint32_t rx_len; 	//
}USB_buftbl;

/*
使用自定义分配缓存方案
	1bit 表示1字节, 512Byte 相当于512bit,相当于64字节
*/

#define USB_BUF_SIZE 	(512)
#define USB_BUFTBL_END 	(0x8 * sizeof(USB_buftbl) / 2)

uint8_t	alloc_bit[USB_BUF_SIZE/8];

TU_ATTR_ALWAYS_INLINE static inline void USB_BUF_freeAll(){
	memset(alloc_bit,0,sizeof(alloc_bit));
	memset(ept_buf_addr,0,sizeof(ept_buf_addr));
	memset(ept_max_packet_size,0,sizeof(ept_max_packet_size));

	memset(ept_recv_buf,0,sizeof(ept_recv_buf));
	memset(ept_recv_len,0,sizeof(ept_recv_len));
	memset(ept_recv_off,0,sizeof(ept_recv_off));

	memset(ept_send_buf,0,sizeof(ept_send_buf));
	memset(ept_send_len,0,sizeof(ept_send_len));
	memset(ept_send_off,0,sizeof(ept_send_off));
}

typedef int (*USB_BUF_find_alloc_fn)(int null_offset);

TU_ATTR_ALWAYS_INLINE static inline uint16_t USB_BUF_alloc(int epnum,int packet_size){
	uint32_t addr = USB_BUFTBL_END;			//跳过描述表
	packet_size = (packet_size+1) & 0xfffe;
	TU_ASSERT(packet_size>=4);			//

	//包的字节对齐
		 if(packet_size<8 ) 	packet_size = 8;
	else if(packet_size<16) 	packet_size = 16;
	else if(packet_size<32) 	packet_size = 32;
	else if(packet_size<64) 	packet_size = 64;

	if(
		packet_size==8||packet_size==16||packet_size==32||packet_size==64
	){
		int 		offset = 0 + addr;
		uint8_t		*bit = alloc_bit;
		while((offset + packet_size)<=USB_BUF_SIZE){				/*缓存大小为512个字节*/
			 uint8_t 		*bit8 =  ( uint8_t*)bit;
			uint16_t 		*bit16 = (uint16_t*)bit;
			uint32_t 		*bit32 = (uint32_t*)bit;
			uint64_t 		*bit64 = (uint64_t*)bit;

			if((packet_size== 8)&&( *bit8==0)){  *bit8=-1; return offset; }
			if((packet_size==16)&&(*bit16==0)){ *bit16=-1; return offset; }
			if((packet_size==32)&&(*bit32==0)){ *bit32=-1; return offset; }
			if((packet_size==64)&&(*bit64==0)){ *bit64=-1; return offset; }

			offset += packet_size;
			bit += packet_size/8;
		}
	}

	TU_ASSERT(0);		//应该处理一些微小的块,8或者16,32,64

	return 0;

	//return addr + epnum * 64*2 /2;						//
}

//结束at32f403a
//////////////////////////////////////////////////////////////////////////////////////////////////

/*------------------------------------------------------------------*/
/* Device API
 *------------------------------------------------------------------*/

int usb_reset = 0;
static void dcd_handle_bus_reset(void){
	//重置中断,需要打开断点0与1
	//初始化一些东西
	USB->devaddr = 0x00;

	USB_BUF_freeAll();

	dcd_edpt_open(0,&ep0OUT_desc);

	dcd_edpt_open(0,&ep0IN_desc);

	usb_reset++;

	USB->devaddr = 0x80;		//设置设备的地址为0
}

// Initialize controller to device mode
void dcd_init (uint8_t rhport)
{
  (void) rhport;

 //需要设置一些USB外设参数
  USB->ctrl_bit.csrst = 0;
  USB->intsts = 0;
  USB->buftbl = 0;			//默认USB表位置
  USB->devaddr = 0x80;		//地址为0,USB core开始工作

	//设置中断
  USB->ctrl |= (USB_SOF_INT | USB_RST_INT | USB_SP_INT | USB_WK_INT | USB_TC_INT);

  dcd_handle_bus_reset();
  //最后开启连接
  dcd_connect(0);
}

// Enable device interrupt
void dcd_int_enable (uint8_t rhport)
{
	INT_EN(1);
}

// Disable device interrupt
void dcd_int_disable (uint8_t rhport)
{
	INT_EN(0);
}

// Receive Set Address request, mcu port must also include status IN response
void dcd_set_address (uint8_t rhport, uint8_t dev_addr)
{
	//SET_ADDR(dev_addr);
	//USB->devaddr_bit.addr = dev_addr; USB->devaddr_bit.cen = 1;
	//USB->devaddr = 0x80;		//只能是0x80

	//响应
	dcd_edpt_xfer(0,TUSB_DIR_IN_MASK | 0x00,NULL,0);

	// 设置address只能在状态完成后设置地址
}

void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request)
{
  (void) rhport;

  if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE &&
      request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
      request->bRequest == TUSB_REQ_SET_ADDRESS )
  {
    uint8_t const dev_addr = (uint8_t) request->wValue;

    // Setting new address after the whole request is complete
	usb_set_address(USB,dev_addr);
  }
}

// Wake up host
void dcd_remote_wakeup (uint8_t rhport)
{
	WAKEUP;
}

// Connect by enabling internal pull-up resistor on D+/D-
void dcd_connect(uint8_t rhport)
{
	CONNECT;
}

// Disconnect by disabling internal pull-up resistor on D+/D-
void dcd_disconnect(uint8_t rhport)
{
	DISCONNECT;
}

void dcd_sof_enable(uint8_t rhport, bool en)
{
	//可以实现.更多不实现
  (void) rhport;
  (void) en;
  // TODO implement later
}

//--------------------------------------------------------------------+
// Endpoint API
//--------------------------------------------------------------------+

// Configure endpoint's registers according to descriptor
bool dcd_edpt_open            (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep){
	//需要实现
  (void) rhport;
  u32 wType;
  switch (desc_ep->bmAttributes.xfer)
  {
  case TUSB_XFER_CONTROL	: wType = USB_EPT_CONTROL;	break;	//控制端口
  case TUSB_XFER_BULK		: wType = USB_EPT_BULK;	break;		//批量传输
  case TUSB_XFER_INTERRUPT	: wType = USB_EPT_INT;	break;		//中断传输
  case TUSB_XFER_ISOCHRONOUS: wType = USB_EPT_ISO;	break;		//同步传输
  default:
  //错误
		TU_ASSERT(0);
	  	break;
  }
  int dir = tu_edpt_dir(desc_ep->bEndpointAddress);					//方向
  int packet_sz = tu_edpt_packet_size(desc_ep);  	//包大小
  uint8_t epnum = tu_edpt_number(desc_ep->bEndpointAddress);

  //设置EP类型,与地址. 使用默认地址
  int ept_v = wType|0;
  int addr =  tu_edpt_number(desc_ep->bEndpointAddress);
  ept_v |= USB_RXTC|USB_TXTC;
  ept_v |= (addr) & 0xF;

  if(epnum>=8) TU_ASSERT(0);

  USB->ept[epnum] = ept_v;	//16位EP属性

  //申请缓存
  uint8_t ep_addr = USB->ept[epnum]&0xf;
  int ep_buf = USB_BUF_alloc(ep_addr,packet_sz);
  ept_buf_addr[epnum][dir] = ep_buf;				//设置接收或者发送地址
  ept_max_packet_size[epnum][dir] = packet_sz;

  if(dir==TUSB_DIR_IN){
	  //设置传送地址
	  //现在不使用双倍缓存
	  USB_SET_TX_ADDRESS(epnum,ep_buf);
	  USB_CLEAR_TXDTS(epnum);
	  USB_SET_TXSTS(epnum,USB_TX_NAK);
  }
  else{
	  //设置接收地址
	  //现在不使用双倍缓存
	  USB_SET_RX_ADDRESS(epnum,ep_buf);
	  USB_CLEAR_RXDTS(epnum);
      USB_SET_RXLEN(epnum, packet_sz);
      USB_SET_RXSTS(epnum, USB_RX_VALID);
  }

  return 1;
}

void dcd_edpt_close_all (uint8_t rhport)
{
	//不实现
  (void) rhport;
}

// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
{
	//需要实现
  (void) rhport;
  (void) ep_addr;
  (void) buffer;
  (void) total_bytes;
  uint8_t epnum = tu_edpt_number(ep_addr);
  u8 dir = tu_edpt_dir(ep_addr);

  if(dir==TUSB_DIR_OUT){
	  //主机输出.设备输入
	  u8 *buf = buffer;
	  if(ep_addr==0 && buffer==NULL){
		  //控制端
		  buf = (uint8_t*)_setup_packet;
	  }

		//设置接收缓存
		ept_recv_buf[epnum] = buf;
		ept_recv_len[epnum] = total_bytes;
		ept_recv_off[epnum] = 0;

		if(total_bytes>ept_max_packet_size[epnum][TUSB_DIR_OUT])
			total_bytes = ept_max_packet_size[epnum][TUSB_DIR_OUT];

		//设置接收数量
		USB_SET_RXLEN(epnum,total_bytes);

	  	//设置可以接收缓存状态
	  	USB_SET_RXSTS(epnum,USB_RX_VALID);
  }
  else{
	  //IN
	  //主机输入,设备输出

		ept_send_buf[epnum] = buffer;
		ept_send_len[epnum] = total_bytes;
		ept_send_off[epnum] = 0;
		dcd_transmit_packet(epnum);
  }
  return 1;
}

#if 0
// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c
bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
{
	//可以不实现
  (void) rhport;
  (void) ep_addr;
  (void) ff;
  (void) total_bytes;
  return 1;
}
#endif

// Stall endpoint
void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
{
	//需要实现
	u8 epnum = tu_edpt_number(ep_addr);
	u8 dir = tu_edpt_dir(ep_addr);
	if(dir==TUSB_DIR_IN)
		{USB_SET_TXSTS(epnum,USB_TX_STALL);}
	else
		{USB_SET_RXSTS(epnum,USB_RX_STALL);}
}

// clear stall, data toggle is also reset to DATA0
void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
{
	//需要实现
	u8 epnum = tu_edpt_number(ep_addr);
	u8 dir = tu_edpt_dir(ep_addr);
	u16 epnum_reg = USB->ept[epnum];
	if(dir==TUSB_DIR_IN){

		if((epnum_reg&USB_TRANS_TYPE)!=USB_EPT_ISO){
			USB_SET_TXSTS(epnum,USB_TX_NAK);	//如果不是ISO,则需要清除
		}

		USB_CLEAR_TXDTS(epnum);
	}
	else{
		if((epnum_reg&USB_TRANS_TYPE)!=USB_EPT_ISO){
			USB_SET_RXSTS(epnum,USB_TX_NAK);	//如果不是ISO,则需要清除
		}

		USB_CLEAR_RXDTS(epnum);
	}
}

static void dcd_ep_ctr_rx_handler(uint32_t wIstr){
	//处理RX数据
	int ept_num = (usb_ept_number_type)(wIstr & USB_EPT_NUM_FLAG);
	uint32_t ept_val = USB->ept[ept_num];
	usb_ept_info *ept_info = &ept_out[ept_num];
	uint8_t ept_addr = (ept_val&0xf);

	//不是RX中断状态
	if((ept_val & USB_RXSTS)==0){
		return;
	}

	if(ept_val&USB_SETUPTC){
		//设置中断请求
		int recv_len = USB_GET_RX_LEN(ept_num);
		if(recv_len==8){
			int rx_addr = ept_buf_addr[ept_num][TUSB_DIR_OUT];
			//printf("%x,%d\n",recv_len_reg,recv_len_v);

			//需要设置RX,TX为等待. 实际上是把setup事件转到fifo时间里
			USB_SET_RXSTS(0,USB_RX_NAK);
			USB_SET_TXSTS(0,USB_TX_NAK);

			usb_read_packet(setup_buffer, rx_addr, recv_len);
			//USB_CLEAR_RXTC(USB_EPT0);

			//设置配置
			dcd_event_setup_received(0,setup_buffer,1);
			//dcd_set_address(0,0);
			//printf("%x,%d\n",1,2);
		}
	}
	else if(ept_val & USB_RXTC){
		//端口输出中断请求

		int len = USB_GET_RX_LEN(ept_num);
		int rx_addr = ept_buf_addr[ept_num][TUSB_DIR_OUT];
		int max_packet = ept_max_packet_size[ept_num][TUSB_DIR_OUT];
		TU_ASSERT(len<=max_packet);		//必须小于等于最大包大小
		uint8_t* buf = ept_recv_buf[ept_num];

		//读取包数据
		usb_read_packet(buf + ept_recv_off[ept_num], rx_addr, len);
		ept_recv_off[ept_num] += len;


		//设置接收数据的长度
		int total_len = ept_recv_len[ept_num];
		int cur_len = ept_recv_off[ept_num];

		USB_CLEAR_RXTC(ept_num);		//清除端口中断

		if(len < max_packet || ept_num == USB_EPT0 || cur_len==total_len)
		{
			/* out transfer complete */
			//usbd_core_out_handler(udev, ept_num);
			dcd_event_xfer_complete(0, ept_addr, len, XFER_RESULT_SUCCESS, true);
		}
		else
		{
			//len == max_packet.
			//处理剩余的接收数据
			int remaining = ept_recv_len[ept_num] - ept_recv_off[ept_num];		//剩余数据
			if(remaining>ept_max_packet_size[ept_num][TUSB_DIR_OUT])
				remaining = ept_max_packet_size[ept_num][TUSB_DIR_OUT];

			//当完成后触发
			USB_SET_RXLEN(ept_num,remaining);
			USB_SET_RXSTS((ept_addr & 0x7F), USB_RX_VALID);
		}

		if(ept_num==USB_EPT0){
			//端点0
			USB_SET_RXLEN(ept_num,CFG_TUD_ENDPOINT0_SIZE);
			USB_CLEAR_RXTC(ept_num);		//清除端口中断
		}
	}

	if(ept_addr==0){
		//准备接收下一个状态包
		USB_SET_RXLEN(0,CFG_TUD_ENDPOINT0_SIZE);
		USB_CLEAR_RXTC(0);
	}
}

static void dcd_transmit_packet(int ept_num){
	uint16_t buf_addr = ept_buf_addr[ept_num][TUSB_DIR_IN];
	uint8_t* buf = ept_send_buf[ept_num];
	uint16_t len = ept_send_len[ept_num];
	uint16_t off = ept_send_off[ept_num];
	uint16_t packet_size = ept_max_packet_size[ept_num][TUSB_DIR_IN];
	int remaining = len - off;
	if(remaining>packet_size)
		remaining = packet_size;

	usb_write_packet(buf+off,buf_addr,remaining);

	ept_send_off[ept_num] += remaining;		//指向下一个数据

	USB_SET_TXLEN(ept_num,remaining);

	//处理发送
	USB_SET_TXSTS(ept_num, USB_TX_VALID);
}

static void dcd_ep_ctr_tx_handler(uint32_t wIstr){
	//处理tx数据
	int ept_num = (usb_ept_number_type)(wIstr & USB_EPT_NUM_FLAG);
	uint32_t ept_val = USB->ept[ept_num];
	uint8_t ept_addr = (ept_val&0xf);
	if((ept_val & USB_TXTC)==0){
		return ;
	}

	//清除中断标识
	USB_CLEAR_TXTC(ept_num);
	//ept_info->trans_len = USB_GET_TX_LEN(ept_num);
	//ept_info->trans_buf += ept_info->trans_len;

	int total_len = ept_send_len[ept_num];
	int offset = ept_send_off[ept_num];

	if(offset!=total_len){
		//继续发送数据
		dcd_transmit_packet(ept_num);
	}
	else{
		//发送完成后的中断.触发complete事件
		dcd_event_xfer_complete(0, ept_num | TUSB_DIR_IN_MASK, total_len, XFER_RESULT_SUCCESS, true);
	}
}

static void dcd_ep_ctr_handler(void)
{
	uint32_t wIstr;

	/* stay in loop while pending interrupts */
	while (((wIstr = USB->intsts) & USB_TC_FLAG) != 0U)
	{
		if ((wIstr & USB_INOUT_FLAG) == 0U) /* TX/IN */
		{
			//TX/ 处理USB IN
			dcd_ep_ctr_tx_handler(wIstr);
		}
		else /* RX/OUT*/
		{
			//RX /处理USB OUT
			dcd_ep_ctr_rx_handler(wIstr);
		}
	}
}

//需要实现中断
void dcd_int_handler(uint8_t rhport) {
	usbd_type *usbx = USB;
	uint32_t sts = usbx->intsts;		//获得usb状态
	uint32_t sts_ien = usbx->ctrl;
	if(sts & USB_TC_FLAG){
		//端点tc中断处理程序
		//处理RX,TX数据
		dcd_ep_ctr_handler();
	}

	if(
			(sts & USB_SOF_FLAG)
			&&(sts_ien & USB_SOF_INT)
	){
		usb_flag_clear(usbx, USB_SOF_FLAG);
		dcd_event_sof(0,usbx->sofrnum_bit.sofnum,1);
	}

	if((sts & USB_RST_FLAG)){
		//usb重置事件
		usb_flag_clear(usbx, USB_RST_FLAG);
		dcd_handle_bus_reset();
		dcd_event_bus_reset(0, TUSB_SPEED_FULL, 1);
		return;
	}

	if((sts & USB_WK_FLAG)&& (sts_ien&USB_WK_INT)){
		//USB上电处理
		usbx->ctrl_bit.ssp = FALSE;
	  	usbx->ctrl_bit.lpm = FALSE;
		usb_flag_clear(usbx, USB_WK_FLAG);
		dcd_event_bus_signal(0, DCD_EVENT_RESUME, 1);
	}

	if((sts & USB_SP_FLAG)
			&& (sts_ien&USB_SP_INT)
			){
		//USB 挂起
		usbx->ctrl_bit.ssp = TRUE;
		usbx->ctrl_bit.lpm = TRUE;
		usb_flag_clear(usbx, USB_SP_FLAG);
		dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, 1);
	}

	if( (sts & USB_LSOF_FLAG) && (sts_ien & USB_SOF_INT)){
		//USB丢失SOF标志
		//SOF中断
		usb_flag_clear(usbx, USB_LSOF_FLAG);
	}
}

int USBFS_L_CAN1_RX0_IRQHandler(){
	//处理中断程序
	dcd_int_handler(0);
	return 0;
}

#endif
